package handin06;

import java.util.ArrayList;

/**
 * VendingMachine holds products.
 * @author Peter Tolstrup Aagesen, ptaa@itu.dk
 *
 */
public class VendingMachine {
	
	//Instantiate supplier
	private Supplier supplier = new Supplier();
	//Amount of product to order at a time
	public static final int ORDERSIZE = 5;
	
	//Arrays of products
	private ArrayList<Product> apples = supplier.orderProducts(ProductType.APPLE, ORDERSIZE);
	private ArrayList<Product> colas = supplier.orderProducts(ProductType.COLA, ORDERSIZE);
	
	//Credit
	private ArrayList<Coin> insertedCoins = new ArrayList<Coin>();
	
	//Constructor
	public VendingMachine()
	{			
	}
	
	/**
	 * insertCoin adds the value of a Coin object to the ArrayList containing the inserted coins
	 * @param coin Coin
	 */
	public void insertCoin(Coin coin)
	{
		//Add value
		insertedCoins.add(coin);
	}
	
	/**
	 * dispenceProduct returns a Product and the reminding coins, if there's not enough coins to buy
	 * the product the reminding coins are returned
	 * @param type ProductType
	 * @return ArrayList<Valuable>
	 */
	public ArrayList<Valuable> dispenceProduct(ProductType type)
	{
		//ArrayList of Valuables (Product and coins) to return
		ArrayList<Valuable> returnedValuables = new ArrayList<Valuable>();
		
		//Product to return
		Product returnedProduct;
		
		switch(type){
			case COLA:
				//Check if there's enough credits
				if(sumOfInsertedCoins() >= colas.get(0).getValue()){
					
					//Set returned Product and remove it from the product arrayList 
					returnedProduct = colas.remove(0);
					
					//Subtract credits
					deductValueFromCoins(returnedProduct.getValue());
					
					//Check if there's no more colas
					if(colas.isEmpty())
					{
						//Order more products
						colas = supplier.orderProducts(returnedProduct.getType(), ORDERSIZE);
					}
					
					//Add Product to valuables array
					returnedValuables.add(returnedProduct);
				} 
				break;
			case APPLE:
				//Check if there's enough credits
				if(sumOfInsertedCoins() >= apples.get(0).getValue()){
					
					//Set returned Product and remove it from the product arrayList 
					returnedProduct = apples.remove(0);
					
					//Subtract credits
					deductValueFromCoins(returnedProduct.getValue());	
					
					//Check if there's more products					
					if(apples.isEmpty())
					{
						//Order more products
						apples = supplier.orderProducts(returnedProduct.getType(), ORDERSIZE);
					}
					
					//Add Product to valuables array
					returnedValuables.add(returnedProduct);
				} 
				break;
			default:	
		}	
		
		while(insertedCoins.size() > 0)
		{
			returnedValuables.add(insertedCoins.remove(0));
		}
		
		
		//Return product
		return returnedValuables;
	}
	
	/**
	 * giveChange returns the inserted coins as an ArrayList
	 * @return ArrayList<Valuable>
	 */
	public ArrayList<Coin> giveChange()
	{
		//Create and set return value
		ArrayList<Coin> returnedCoins = new ArrayList<Coin>();
		
		while (insertedCoins.size() > 0)
		{
			returnedCoins.add(insertedCoins.remove(0));
		}
		
		//Return 
		return returnedCoins;
	}
	
	/**
	 * toString returns a String describing the state of the VendingMachine
	 */
	public String toString()
	{
		String returnString = "";
		
		returnString += "This vending machine holds following products: \n";
		returnString += apples.size() + " apples at " + apples.get(0).getValue() + "$\n";
		returnString += colas.size() + " colas at " + colas.get(0).getValue() + "$\n";
		returnString += "You have " + sumOfInsertedCoins() + " credits.";
		
		return returnString;
	}
	
	/**
	 * sumOfInsertedCoins returns the value of the inserted coins
	 * @return double
	 */
	private double sumOfInsertedCoins()
	{
		//
		double countValue = 0;
		
		//Count coins
		for(Coin coin: insertedCoins){
			countValue += coin.getValue();
		}
		
		//Return
		return countValue;
	}
	
	/**
	 * deductValueFromCoins remove a value from the inserted coins array
	 * @param value double
	 */
	private void deductValueFromCoins(double value)
	{
		//Copy value to a variable
		double remainingValue = value;
		
		//
		while (remainingValue > 0.01 && !insertedCoins.isEmpty())
		{
			//Get the current coin
			Coin currentCoin = insertedCoins.get(0);
			
			//If the value of the current coin i less than the remaining value
			if(remainingValue > currentCoin.getValue()){
				
				//Subtract coin value from remaining value
				remainingValue -= currentCoin.getValue();
				
				//Remove coin
				insertedCoins.remove(currentCoin);
			
			//If the value of the coin is more than the remaining value
			} else {
				
				//Store the value of the coin
				double remainingCoinValue = currentCoin.getValue();
				
				//Subtract the remaining value
				remainingCoinValue -= remainingValue;
				
				//Remove the coin
				insertedCoins.remove(currentCoin);
				
				//Add coins up to the remaining coin value
				//Quarters
				while (remainingCoinValue > 0.25)
				{
					insertedCoins.add(new Nickel());
					remainingCoinValue -= 0.25;
				}
				//Dimes
				while (remainingCoinValue > 0.1)
				{
					insertedCoins.add(new Dime());
					remainingCoinValue -= 0.1;
				}
				//Nickels
				while (remainingCoinValue > 0.05)
				{
					insertedCoins.add(new Nickel());
					remainingCoinValue -= 0.05;
				}
				//Pennies
				while (remainingCoinValue > 0.01)
				{
					insertedCoins.add(new Penny());
					remainingCoinValue -= 0.01;
				}		
				break;
			}
		}		
	}
}
